package top.chmin.project.cloud.common.entity;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * chmin
 * 2023/12/19 13:33
 * cloud-builder
 */
public abstract class LocalDateTimeFPCField<T extends PreCondition> {

    T t;
    String columnName;

    public LocalDateTimeFPCField(T t, String columnName) {
        this.t = t;
        this.columnName = columnName;
    }

    public T eq(LocalDateTime valueId) {
        t.addSql(columnName + " = ?", valueId);
        return t;
    }

    public T ne(LocalDateTime valueId) {
        t.addSql(columnName + " <> ?", valueId);
        return t;
    }

    public T lt(LocalDateTime valueId) {
        t.addSql(columnName + " < ?", valueId);
        return t;
    }

    public T gt(LocalDateTime valueId) {
        t.addSql(columnName + " > ?", valueId);
        return t;
    }

    public T le(LocalDateTime valueId) {
        t.addSql(columnName + " <= ?", valueId);
        return t;
    }

    public T ge(LocalDateTime valueId) {
        t.addSql(columnName + " >= ?", valueId);
        return t;
    }

    public T in(LocalDateTime... valueIds) {
        t.addSql(columnName + " IN (%s)".formatted(
                Stream.of(valueIds).map(t -> "?").collect(Collectors.joining(", "))
        ), valueIds);
        return t;
    }

    public T in(List<LocalDateTime> valueIds) {
        t.addSqlLocalDateTime(columnName + " IN (%s)".formatted(
                valueIds.stream().map(t -> "?").collect(Collectors.joining(", "))
        ), valueIds);
        return t;
    }

    public T notIn(LocalDateTime... valueIds) {
        t.addSql(columnName + " NOT IN (%s)".formatted(
                Stream.of(valueIds).map(t -> "?").collect(Collectors.joining(", "))
        ), valueIds);
        return t;
    }

    public T notIn(List<LocalDateTime> valueIds) {
        t.addSqlLocalDateTime(columnName + " NOT IN (%s)".formatted(
                valueIds.stream().map(t -> "?").collect(Collectors.joining(", "))
        ), valueIds);
        return t;
    }

    public T between(LocalDateTime start, LocalDateTime end) {
        t.addSql(columnName + " BETWEEN (?, ?)", start, end);
        return t;
    }

    public T group() {
        t.addGroup(columnName);
        return t;
    }

    public T asc() {
        t.addOrder(columnName);
        return t;
    }

    public T desc() {
        t.addOrder(columnName + " DESC");
        return t;
    }

    public T select() {
        t.addSelect(columnName);
        return t;
    }

    public T as(String fieldName) {
        t.addSelect(columnName, fieldName);
        return t;
    }

    public T count() {
        t.addSelect("COUNT(%s)".formatted(columnName));
        return t;
    }

    public T countAs(String fieldName) {
        t.addSelect("COUNT(%s) AS %s".formatted(columnName, fieldName));
        return t;
    }

    public T min() {
        t.addSelect("MIN(%s)".formatted(columnName));
        return t;
    }

    public T minAs(String fieldName) {
        t.addSelect("MIN(%s) AS %s".formatted(columnName, fieldName));
        return t;
    }

    public T max() {
        t.addSelect("MAX(%s)".formatted(columnName));
        return t;
    }

    public T maxAs(String fieldName) {
        t.addSelect("MAX(%s) AS %s".formatted(columnName, fieldName));
        return t;
    }

    public T sum() {
        t.addSelect("SUM(%s)".formatted(columnName));
        return t;
    }

    public T sumAs(String fieldName) {
        t.addSelect("SUM(%s) AS %s".formatted(columnName, fieldName));
        return t;
    }

    public T avg() {
        t.addSelect("AVG(%s)".formatted(columnName));
        return t;
    }

    public T avgAs(String fieldName) {
        t.addSelect("AVG(%s) AS %s".formatted(columnName, fieldName));
        return t;
    }
}
